package com.organization

import grails.test.*
import grails.converters.JSON

class DataControllerTests extends GrailsUnitTestCase {

    DataController controller
    DataService dataService
    CommonService commonService

    protected void setUp() {
        super.setUp()
        //create and save data objects
        def dep = new Department(name: "Dep1")
        def proj = new Project(name: "Proj1", startDate: new Date())
        def empl = new Employee(lastName: "Ivanov", firstName: "Ivan")
        dep.addToProjects(proj)
        proj.addToEmployees(empl)
        assertNotNull "can't save department",dep.save()
        assertNotNull "can't save project",proj.save()
        assertNotNull "can't save employee",empl.save()
        //init controller
        controller = new DataController()
        controller.dataService = dataService
    }

    protected void tearDown() {
        super.tearDown()
    }

    //test getTitle action
    void testGetTitle() {
        controller.getTitle()
        //parse the JSON
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        //navigate the JSON as an object
        assertNotNull "Missing success field", jsonResult.success
        assertNotNull "Missing name field", jsonResult.name
        assertEquals "true", jsonResult.success
        assertEquals commonService.rootNodeStr, jsonResult.name
    }

    //test getElement action for not existing node
    void testGetElementForUnknown(){
        controller.params.nodeId = "NotExistingNode_123123"
        controller.getElement()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        assertEquals "false", jsonResult.success
    }

    //test getElement action for root
    void testGetElementForRoot(){
        controller.params.nodeId = commonService.rootNodeStr
        controller.getElement()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        assertEquals "true", jsonResult.success
        assertEquals commonService.rootNodeStr, jsonResult.name
    }

    //test getElement action for department node
    void testGetElementForDepartment(){
        def dep = Department.findByName("Dep1")
        assertNotNull "can't find department",dep

        controller.params.nodeId = "Department_"+dep.id
        controller.getElement()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        assertNotNull "Missing success field", jsonResult.success
        assertNotNull "Missing name field", jsonResult.name
        assertEquals "true", jsonResult.success
        assertEquals "Dep1", jsonResult.name
    }

    //test getElement action for project node
    void testGetElementForProject(){
        def proj = Project.findByName("Proj1")
        assertNotNull "can't find project",proj

        controller.params.nodeId = "Project_"+proj.id
        controller.getElement()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        assertNotNull "Missing success field", jsonResult.success
        assertNotNull "Missing name field", jsonResult.name
        assertEquals "true", jsonResult.success
        assertEquals "Proj1", jsonResult.name
    }

    //test getElement action for employee node
    void testGetElementForEmployee(){
        def empl = Employee.findByLastName("Ivanov")
        assertNotNull "can't find employee",empl

        controller.params.nodeId = "Employee_"+empl.id
        controller.getElement()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        assertNotNull "Missing success field", jsonResult.success
        assertNotNull "Missing lastName field", jsonResult.lastName
        assertEquals "true", jsonResult.success
        assertEquals "Ivanov", jsonResult.lastName
    }

    //test update action for not existing
    void testUpdateForUnknown(){
        controller.params.nodeId = "Department_123"
        controller.params.name = "Dep2"
        controller.params.dateCreated = "2012-01-01"
        controller.params.description = "Description"
        controller.update()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        assertEquals "false", jsonResult.success
    }

    //test update action for department node
    void testUpdateForDepartment(){
        def dep = Department.findByName("Dep1")
        assertNotNull "can't find department",dep

        controller.params.nodeId = "Department_"+dep.id
        controller.params.name = "Dep2"
        controller.params.dateCreated = "2012-01-01"
        controller.params.description = "Description"
        controller.update()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        assertEquals "true", jsonResult.success
        assertEquals "Dep2", jsonResult.newName
        assertEquals "Department_"+dep.id, jsonResult.nodeId
    }

    //test update action for project node
    void testUpdateForProject(){
        def proj = Project.findByName("Proj1")
        assertNotNull "can't find project",proj

        controller.params.nodeId = "Project_"+proj.id
        controller.params.name = "Proj2"
        controller.params.startDate = "2012-01-01"
        controller.params.dueDate = "2012-01-31"
        controller.params.description = "Description"
        controller.update()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        assertEquals "true", jsonResult.success
        assertEquals "Proj2", jsonResult.newName
        assertEquals "Project_"+proj.id, jsonResult.nodeId
    }

    //test update action for employee node
    void testUpdateForEmployee(){
        def empl = Employee.findByLastName("Ivanov")
        assertNotNull "can't find employee",empl

        controller.params.nodeId = "Employee_"+empl.id
        controller.params.lastName = "Petrov"
        controller.params.firstName = "Petr"
        controller.params.hireDate = "2012-01-01"
        controller.params.workPosition = "Position"
        controller.params.extensionPhone = "1234"
        controller.params.mobilePhone = "+79051919891"
        controller.params.homePhone = "123456"
        controller.params.email = "email@email.com"
        controller.params.addressStreetCity = "Rodionova, NN"
        controller.params.addressHouse = "123"
        controller.params.addressApartment = "1232"
        controller.params.birthDate = "1981-12-17"
        controller.params.gender = "M"
        controller.update()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        assertEquals "true", jsonResult.success
        assertEquals "Petrov Petr", jsonResult.newName
        assertEquals "Employee_"+empl.id, jsonResult.nodeId
    }

    //test add action for not existing node
    void testAddForUnknown(){
        controller.params.parentNodeId = "NotExistingParent"
        controller.params.name = "Dep3"
        controller.params.dateCreated = "2012-01-01"
        controller.params.description = "Description"
        controller.add()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        def dep = Department.findByName("Dep3")
        assertNull "department was added",dep
        assertEquals "false", jsonResult.success
    }

    //test add action for root node
    void testAddForRoot(){
        controller.params.parentNodeId = commonService.rootNodeStr
        controller.params.name = "Dep3"
        controller.params.dateCreated = "2012-01-01"
        controller.params.description = "Description"
        controller.add()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        def dep = Department.findByName("Dep3")
        assertNotNull "can't find department",dep
        assertEquals "true", jsonResult.success
        assertEquals commonService.rootNodeStr, jsonResult.parentNodeId
        assertEquals "Department_"+dep.id, jsonResult.nodeId
    }

    //test add action for department node
    void testAddForDepartment(){
        def dep = Department.findByName("Dep1")
        assertNotNull "can't find department",dep

        controller.params.parentNodeId = "Department_"+dep.id
        controller.params.name = "Proj3"
        controller.params.startDate = "2012-01-01"
        controller.params.dueDate = "2012-01-31"
        controller.params.description = "Description"
        controller.add()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        def proj = Project.findByName("Proj3")
        assertNotNull "can't find project",proj
        assertEquals "true", jsonResult.success
        assertEquals "Department_"+dep.id, jsonResult.parentNodeId
        assertEquals "Project_"+proj.id, jsonResult.nodeId
    }

    //test add action for project node
    void testAddForProject(){
        def proj = Project.findByName("Proj1")
        assertNotNull "can't find project",proj

        controller.params.parentNodeId = "Project_"+proj.id
        controller.params.lastName = "Nesterov"
        controller.params.firstName = "Igor"
        controller.params.hireDate = "2012-01-01"
        controller.params.workPosition = "Position"
        controller.params.extensionPhone = "1234"
        controller.params.mobilePhone = "+79051919891"
        controller.params.homePhone = "123456"
        controller.params.email = "email@email.com"
        controller.params.addressStreetCity = "Rodionova, NN"
        controller.params.addressHouse = "123"
        controller.params.addressApartment = "1232"
        controller.params.birthDate = "1981-12-17"
        controller.params.gender = "M"
        controller.add()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        def empl = Employee.findByLastName("Nesterov")
        assertNotNull "can't find employee",empl
        assertEquals "true", jsonResult.success
        assertEquals "Project_"+proj.id, jsonResult.parentNodeId
        assertEquals "Employee_"+empl.id, jsonResult.nodeId
    }

    //test delete action for not existing node
    void testDeleteForNotExists(){
        controller.params.nodeId = "Department_123123"
        controller.delete()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        assertEquals "false", jsonResult.success
    }

    //test delete action for department node
    void testDeleteForDepartment(){
        //find existing department
        def dep = Department.findByName("Dep1")
        assertNotNull "can't find department",dep
        //find children elements for department
        def proj = Project.findByName("Proj1")
        assertNotNull "can't find project",proj
        def empl = Employee.findByLastName("Ivanov")
        assertNotNull "can't find employee",empl

        //delete department
        controller.params.nodeId = "Department_"+dep.id
        controller.delete()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        assertEquals "true", jsonResult.success
        assertFalse "Department exists", Department.exists(dep.id)
        assertFalse "Project exists", Project.exists(proj.id)
        assertFalse "Employee exists", Employee.exists(empl.id)
    }

    //test delete action for project node
    void testDeleteForProject(){
        //find existing project
        def proj = Project.findByName("Proj1")
        assertNotNull "can't find project",proj
        //find children elements for project
        def empl = Employee.findByLastName("Ivanov")
        assertNotNull "can't find employee",empl
        //find parent elements for project
        def dep = Department.findByName("Dep1")
        assertNotNull "can't find department",dep

         //delete project
        controller.params.nodeId = "Project_"+proj.id
        controller.delete()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        assertEquals "true", jsonResult.success
        assertTrue "Department not exists", Department.exists(dep.id)
        assertFalse "Project exists", Project.exists(proj.id)
        assertFalse "Employee exists", Employee.exists(empl.id)
    }

    //test delete action for employee node
    void testDeleteForEmployee(){
        //find existing employee
        def empl = Employee.findByLastName("Ivanov")
        assertNotNull "can't find employee",empl
        //find parent elements for project
        def dep = Department.findByName("Dep1")
        assertNotNull "can't find department",dep
        def proj = Project.findByName("Proj1")
        assertNotNull "can't find project",proj

        //delete employee
        controller.params.nodeId = "Employee_"+empl.id
        controller.delete()
        def controllerResponse = controller.response.contentAsString
        def jsonResult = JSON.parse(controllerResponse)
        assertEquals "true", jsonResult.success
        assertTrue "Department not exists", Department.exists(dep.id)
        assertTrue "Project not exists", Project.exists(proj.id)
        assertFalse "Employee exists", Employee.exists(empl.id)
    }



}
